有了資料表跟Bean,我們就可以進行存取了
儲存資料的部分很單純,因為只有新增資料這一個行為。
所以API只建立一個
Properties:
Path: /message/{catalog}
Method: PUT
handler的地方也很簡單,只要進行儲存就可以了,以下是精簡的實作
String catalog = input.getPath("catalog");
Message message = input.getBody(Message.class);
if (StringUtils.isNullOrEmpty(catalog))
return new ResponseBean(500);
message.setCatalog(catalog);
DynamoDBMapper mapper = new DynamoDBMapper(DBClientFactory.getAmazonDynamoDB());
mapper.save(message);
return new ResponseBean(message);
因為資料表我們設計可以放很多種不同的時間序列,以partition key做為區分查詢。所以我們只需要用catalog查詢即可撈取最新資料。
假設我們想要撈取最新十筆資料
String catalog = input.getPath("catalog");
Message message = new Message();
message.setCatalog(catalog);
DynamoDBMapper mapper = new DynamoDBMapper(DBClientFactory.getAmazonDynamoDB());
List<?> list = mapper.query(Message.class,
new DynamoDBQueryExpression<Message>()
.withHashKeyValues(message)
.withScanIndexForward(false)
.withLimit(10));
return new ResponseBean(list.toArray());
其中ScanIndexForward預設為true,項目以Range Key字母順序或數字大小讀取,所以這邊設為false,以時間字串來說則是最新的資料為先。
但是通常時間序列的資料很多,有時候會希望以日期時間條件及分頁方式查詢,這邊介紹分頁的處理方式。
原則上當我們想用分頁顯示資料時,都代表資料量很大,如果預先抓取全部資料後篩選分頁內容是很浪費效能的。在這方面,DynamoDB API提供LastEvaluatedKey的做法,這不論是queryPage或scanPage等都可以這樣使用。
在使用page查詢方式時回傳的ResultPage會提供results、lastEvaluatedKey、count、scannedCount等屬性如下
(為了方便測試圖中以limit(2)查詢)
在使用page查詢方法時若提供設定exclusiveStartKey,回傳的page則以該key之後繼續讀取。
所以若實作get API
Path: /message/{catalog}
Path: /message/{catalog}/{last}
當path variable last有值時則在查詢增加start key即可
String catalog = input.getPath("catalog");
Message message = new Message();
message.setCatalog(catalog);
DynamoDBMapper mapper = new DynamoDBMapper(DBClientFactory.getAmazonDynamoDB());
DynamoDBQueryExpression<Message> expr = new DynamoDBQueryExpression<Message>()
.withHashKeyValues(message)
.withScanIndexForward(false)
.withLimit(10);
String last = input.getPath("last");
if (!StringUtils.isNullOrEmpty(last)) {
Map<String, AttributeValue> lastKey = new HashMap<String, AttributeValue>();
lastKey.put("pk", new AttributeValue().withS(catalog));
lastKey.put("sk", new AttributeValue().withS(last));
expr.setExclusiveStrtKey(lastKey);
}
QueryResultPage<Message> list = mapper.queryPage(Message.class, expr);
return new ResponseBean(list);
舉例來說上面截圖即是使用GET http://localhost:3000/message/book/2019-10-10T07:54:14.242Z
取得下一頁的資料的。
最後是,對於ResultPage建議還是自己自訂response payload呈現,避免lastEvaluatedKey直接曝露pk、sk,你也會注意到sk實際上在dynamodb儲存的時間格式跟前篇json定義的datetime字串格式並不一樣,這些都是可以再處理的細節。